package com.xinsoft.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xinsoft.common.exception.BDException;
import com.xinsoft.entity.dto.ExcelErrRowDTO;
import com.xinsoft.entity.dto.MesStationDTO;
import com.xinsoft.entity.dto.MesStationPageParam;
import com.xinsoft.entity.dto.SysSupplierDTO;
import com.xinsoft.entity.po.MesStation;
import com.xinsoft.entity.po.SysSupplier;
import com.xinsoft.entity.po.SysUser;
import com.xinsoft.service.MesStationService;
import com.xinsoft.mapper.MesStationMapper;
import com.xinsoft.service.SysFileHisService;
import com.xinsoft.service.SysUserService;
import com.xinsoft.utils.ExcelUtils;
import com.xinsoft.utils.TokenUtil;
import com.xinsoft.validator.ValidatorUtils;
import org.apache.commons.lang.StringUtils;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
* @author hsm
* @description 针对表【mes_station(工位)】的数据库操作Service实现
* @createDate 2023-07-17 13:37:51
*/
@Service
public class MesStationServiceImpl extends ServiceImpl<MesStationMapper, MesStation>
    implements MesStationService{

    @Resource
    private SysUserService sysUserService;
    @Resource
    private SysFileHisService sysFileHisService;

    @Override
    public IPage<MesStation> findPageListByParam(MesStationPageParam param) {
        //分页
        Page<MesStation> page = new Page<MesStation>(param.getCurrentPage(), param.getPageSize());
        QueryWrapper<MesStation> queryWrapper = new QueryWrapper<>();
        //查询条件
        queryWrapper.like(StringUtils.isNotEmpty(param.getStationName()),"station_name", param.getStationName());
        queryWrapper.eq(param.getAuditStatus()!=null,"audit_status",param.getAuditStatus());
        queryWrapper.orderByDesc("update_time");
        IPage<MesStation> resultPage = this.baseMapper.selectPage(page, queryWrapper);
        //返回值
        return resultPage;
    }

    @Override
    public MesStation addMesStation(MesStation mesStation) {
        // 名称和编号 验重

        // 判断名称是否重复
        QueryWrapper<MesStation> nameQuery = new QueryWrapper<>();
        nameQuery.select("id");
        nameQuery.eq("station_name",mesStation.getStationName());
        List names = this.list(nameQuery);

        if(CollectionUtil.isNotEmpty(names)){
            throw new BDException("操作失败，工位名称重复！");
        }

        //判断编号否重复
        QueryWrapper<MesStation> codeQuery = new QueryWrapper<>();
        codeQuery.select("id");
        codeQuery.eq("station_code",mesStation.getStationCode());
        List codes = this.list(codeQuery);
        if(CollectionUtil.isNotEmpty(codes)) {
            throw new BDException("操作失败，工位编号重复！");
        }
        mesStation.setAuditStatus(0);
        mesStation.setAuditId(null);
        save(mesStation);
        return mesStation;
    }

    @Override
    public MesStation editMesStation(MesStation mesStation) {
        //判断编号否重复
        QueryWrapper<MesStation> nameQuery = new QueryWrapper<>();
        nameQuery.select("id");
        nameQuery.eq("station_name",mesStation.getStationName());
        nameQuery.ne("id",mesStation.getId());
        List names = this.list(nameQuery);

        if(CollectionUtil.isNotEmpty(names)){
            throw new BDException("操作失败，工位名称重复！");
        }

        //判断客户社会信用统一码是否重复
        QueryWrapper<MesStation> codeQuery = new QueryWrapper<>();
        codeQuery.select("id");
        codeQuery.eq("station_code",mesStation.getStationCode());
        codeQuery.ne("id",mesStation.getId());
        List codes = this.list(codeQuery);
        if(CollectionUtil.isNotEmpty(codes)) {
            throw new BDException("操作失败，工位编号重复！");
        }

        MesStation entity = getById(mesStation.getId());
        if(Objects.equals(entity.getAuditStatus(),1)){
            throw new BDException("操作失败，已审核无法编辑！");
        }
        mesStation.setAuditStatus(0);
        mesStation.setAuditId(null);
        updateById(mesStation);
        return mesStation;
    }

    @Override
    public void del(List<Integer> ids) {

        QueryWrapper<MesStation> query = new QueryWrapper<>();
        query.eq("audit_status",1);//审核
        List<MesStation> list = this.list(query);
        //判断是否已启用
        if(CollectionUtil.isNotEmpty(list)){
            throw new BDException("操作失败，"+list.get(0).getStationName()+"已审核无法删除！");
        }

        this.removeByIds(ids);
    }

    @Override
    public MesStationDTO getMesStation(Integer id) {
        MesStationDTO mesStationDTO = new MesStationDTO();
        MesStation mesStation = this.getById(id);
        BeanUtils.copyProperties(mesStation,mesStationDTO);
        //获取审核人
        SysUser user = sysUserService.getById(mesStation.getAuditId());
        if(user!= null){
            mesStationDTO.setAuditName(user.getRealName());
        }



        return mesStationDTO;
    }

    @Override
    public void audit(List<Integer> ids) {
        UpdateWrapper<MesStation> mesStationUpdateWrapper = new UpdateWrapper<>();
        mesStationUpdateWrapper.set("audit_status",1);//审核
        mesStationUpdateWrapper.set("audit_id", TokenUtil.getUserId());//设置审核人
        mesStationUpdateWrapper.in("id",ids);
        mesStationUpdateWrapper.eq("do_delete",0);
        this.update(mesStationUpdateWrapper);
    }

    @Override
    public void deAudit(List<Integer> ids) {
        UpdateWrapper<MesStation> mesStationUpdateWrapper = new UpdateWrapper<>();
        mesStationUpdateWrapper.set("audit_status",0);//审核
        mesStationUpdateWrapper.set("audit_id", TokenUtil.getUserId());//设置审核人
        mesStationUpdateWrapper.in("id",ids);
        mesStationUpdateWrapper.eq("do_delete",0);
        this.update(mesStationUpdateWrapper);
    }

    @Override
    public JSONObject importExcel(MultipartFile multipartFile, HttpServletResponse response) throws IOException {
        // 初始化错误行信息list，用来记录导入失败的rowNum
        List<ExcelErrRowDTO> errRowDOs = new ArrayList<>();

        // 对excel是否为空进行check
        if (multipartFile.isEmpty()) {
            throw new BDException("导入失败，请选择文件！");
        }

        //设置excel参数
        ImportParams params = new ImportParams();
        params.setTitleRows(1);
        params.setHeadRows(1);
        List<MesStationDTO> mesStationsList;
        List<MesStation> mesStations = CollectionUtil.newArrayList();

        JSONObject result = new JSONObject();

        // 解析excel中的行，放到sysSupplierList中
        try {
            // 解析excel
            mesStationsList = ExcelImportUtil.importExcel(multipartFile.getInputStream(), MesStationDTO.class, params);
        } catch (Exception e) {
            throw new BDException("导入失败，文件内容解析错误！");
        }

        //取出excel和db中所有重复的name
        List<String> excelSupplierNames = mesStationsList.stream()
                .map(MesStationDTO::getStationName)
                .collect(Collectors.toList()); // 获取excel中所有的username
        List<String> dbNames = this.getAllName();//获取系统中所有的name
        List<String> duplicateNames = new ArrayList<>(); // 存放存在重复的name，用于定位重复存放存在重复的name的行

        if (dbNames.size() > 0 && excelSupplierNames.size() > 0) {
            dbNames.addAll(excelSupplierNames);//合并
            duplicateNames = ExcelUtils.getDuplicateElements(dbNames);//取出存在重复的name
        }

        //取出excel和db中所有重复的code
        List<String> excelSupplierCodes = mesStationsList.stream()
                .map(MesStationDTO::getStationCode)
                .collect(Collectors.toList()); // 获取excel中所有的username
        List<String> dbSupplierCodes = this.getAllCode();//获取系统中所有的code
        List<String> duplicateCodes = new ArrayList<>(); // 存放存在重复的code，用于定位重复存放存在重复的code的行

        if (dbSupplierCodes.size() > 0 && excelSupplierCodes.size() > 0) {
            dbSupplierCodes.addAll(excelSupplierCodes);//合并
            duplicateCodes = ExcelUtils.getDuplicateElements(dbSupplierCodes);//取出存在重复的username
        }

        //校验
        if (mesStationsList.size() > 0) {

            int index = 1;
            for (MesStationDTO mesStationDTO : mesStationsList) {
                index ++;
                // check
                StringBuilder stringBuilder = new StringBuilder();
                ExcelErrRowDTO excelErrRowDO= new ExcelErrRowDTO();

                // 参数校验
                stringBuilder.append(ValidatorUtils.validateExcel(mesStationDTO));

                // 检验supplierName 是否重复
                if(duplicateNames.contains(mesStationDTO.getStationName())){
                    stringBuilder.append("名称已经存在，请勿重复！");
                }
                // 检验supplierCode 是否重复
                if(duplicateCodes.contains(mesStationDTO.getStationCode())){
                    stringBuilder.append("编号已经存在，请勿重复！");
                }

                // 将错误行信息保存到list
                String errMsg = stringBuilder.toString();
                if(StringUtils.isNotEmpty(errMsg)){
                    excelErrRowDO.setRowIndex(index);
                    excelErrRowDO.setErrMessage(errMsg);
                    errRowDOs.add(excelErrRowDO);
                    continue;
                }
                //保存
                MesStation mesStation = new MesStation();
                BeanUtils.copyProperties(mesStationDTO,mesStation);
                mesStations.add(mesStation);
            }
            saveBatch(mesStations);

            // 导出错误行
            String errFileUrl = ExcelUtils.exportErrRows(errRowDOs,multipartFile,sysFileHisService);
            result.put("errFileUrl",errFileUrl);
        }
        return result;
    }

    private List<String> getAllCode() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("station_code");
        List<MesStation> userList = this.list();
        List<String> codes = userList.stream().map(MesStation::getStationCode).collect(Collectors.toList());
        return codes;
    }

    private List<String> getAllName() {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("station_name");
        List<MesStation> userList = this.list();
        List<String> names = userList.stream().map(MesStation::getStationName).collect(Collectors.toList());
        return names;
    }
}




